#include "VSAnimTree.h"
#include "VSAnimFunction.h"
#include "VSAnimMainFunction.h"
#include "VSAnimBaseFunction.h"
#include "VSAnimSequenceFunc.h"
#include "VSIKController.h"
#include "VSOneParamAnimBlend.h"
#include "VSRectAnimBlend.h"
#include "VSGraphicInclude.h"
#include "VSStream.h"
using namespace VSEngine2;
IMPLEMENT_RTTI(VSAnimTree,VSController)
static bool gs_bStreamRegistered_VSAnimTree= VSAnimTree::RegisterMainFactory();
bool VSAnimTree::ms_bRegisterMainFactory = false;
bool VSAnimTree::RegisterMainFactory()
{
	if (!ms_bRegisterMainFactory)
	{ 
		VSMain::AddInitialFuntion(VSAnimTree::InitialClassFactory); 
		ms_bRegisterMainFactory = true;
	} 
	return ms_bRegisterMainFactory;

}
bool VSAnimTree::InitialClassFactory()
{
	ms_ClassFactory.AddElement(ms_Type.GetName(),FactoryFunc);
	
	return 1;
}
VSObject * VSAnimTree::FactoryFunc()
{
	return VS_NEW VSAnimTree();

}
VSAnimTree::~VSAnimTree()
{
	for(unsigned int i = 0 ; i < m_pAnimFunctionArray.GetNum() ; i++)
	{
		VSAnimBaseFunction * pAnimFunction = m_pAnimFunctionArray[i];
		m_pAnimFunctionArray[i] = NULL;
		VSMAC_DELETE(pAnimFunction);
	}
	
	m_pAnimFunctionArray.Clear();

	m_pAnimMainFunction = NULL;
}
VSAnimTree::VSAnimTree(VSSkelectonMeshNode * pSkelectonMesh)
{
	VSMAC_ASSERT(pSkelectonMesh);

	pSkelectonMesh->AddController(this);
	m_pAnimFunctionArray.Clear();
	m_pAnimMainFunction = NULL;

	m_pAnimMainFunction = VS_NEW VSAnimMainFunction(_T("AnimTree"),this);
	VSMAC_ASSERT(m_pAnimMainFunction);



}
VSAnimTree::VSAnimTree()
{
	m_pAnimFunctionArray.Clear();
	m_pAnimMainFunction = NULL;

}
const VSSkelectonMeshNode * VSAnimTree::GetSkelectonMeshNode()const
{
	return DynamicCast<VSSkelectonMeshNode>(m_pObject);
}
void VSAnimTree::AddAnimFunction(VSAnimBaseFunction * pAnimFunction)
{
	if(pAnimFunction)
	{
		m_pAnimFunctionArray.AddElement(pAnimFunction);
	}
}
bool VSAnimTree::Register(VSStream & rStream)const
{
	if (rStream.IsObjectRegister(this))
	{
		return 1;
	}
	if(!VSController::Register(rStream))
		return 0;

	if(m_pAnimMainFunction)
		if(!m_pAnimMainFunction->Register(rStream))
			return 0;
	for(unsigned int i = 0 ; i < m_pAnimFunctionArray.GetNum() ; i++)
	{
		if(m_pAnimFunctionArray[i])
			if(!m_pAnimFunctionArray[i]->Register(rStream))
				return 0;
	}
	return 1;
}
unsigned int VSAnimTree::DiskUse()const
{
	unsigned int Used = VSController::DiskUse();

	Used +=sizeof(VSAnimMainFunction *);

	Used +=sizeof(VSAnimBaseFunction *) * m_pAnimFunctionArray.GetNum();
	Used +=sizeof(unsigned int);
	return Used;
}
bool VSAnimTree::Save(VSStream & rStream,unsigned int &iSaveUse)const
{
	if(!VSController::Save(rStream,iSaveUse))
		return 0;

// 	VSAnimMainFunction * pAnimMainFunction = m_pAnimMainFunction;
// 	if(!rStream.Write(&pAnimMainFunction,sizeof(VSAnimMainFunction *)))
// 		return 0;
	if(!rStream.WriteObjectPtr(m_pAnimMainFunction))
		return 0;
	iSaveUse += sizeof(VSAnimMainFunction *);

	unsigned int uiFunctionNum = m_pAnimFunctionArray.GetNum();
	if(!rStream.Write(&uiFunctionNum,sizeof(unsigned int)))
		return 0;
	iSaveUse += sizeof(unsigned int);

	for(unsigned int i = 0 ; i < uiFunctionNum ; i++)
	{
// 		VSAnimBaseFunction * pAnimFunction = m_pAnimFunctionArray[i];
// 		if(!rStream.Write(&pAnimFunction,sizeof(VSAnimBaseFunction *)))
// 			return 0;
		if(!rStream.WriteObjectPtr(m_pAnimFunctionArray[i]))
			return 0;
		iSaveUse += sizeof(VSAnimBaseFunction *);
	}

	
	return 1;
}
bool VSAnimTree::Load(VSStream & rStream,unsigned int &iSaveUse)
{	
	if(!VSController::Load(rStream,iSaveUse))
		return 0;

// 	VSAnimMainFunction * pAnimMainFunction = NULL;
// 	if(!rStream.Read(&pAnimMainFunction,sizeof(VSAnimMainFunction *)))
// 		return 0;
// 	AddLink(pAnimMainFunction);
	if(!rStream.ReadObjectPtr(m_pAnimMainFunction))
		return 0;
	iSaveUse += sizeof(VSAnimMainFunction *);

	unsigned int uiFunctionNum = 0;
	if(!rStream.Read(&uiFunctionNum,sizeof(unsigned int)))
		return 0;
	iSaveUse += sizeof(unsigned int);

	m_pAnimFunctionArray.SetBufferNum(uiFunctionNum);
	for(unsigned int i = 0 ; i < uiFunctionNum ; i++)
	{
// 		VSAnimBaseFunction * pAnimFunction = NULL;
// 		if(!rStream.Read(&pAnimFunction,sizeof(VSAnimBaseFunction *)))
// 			return 0;
// 		AddLink(pAnimFunction);
		if(!rStream.ReadObjectPtr(m_pAnimFunctionArray[i]))
			return 0;
		iSaveUse += sizeof(VSAnimBaseFunction *);
	}

	return 1;
}
bool VSAnimTree::Link(VSStream & rStream)
{
	if(!VSController::Link(rStream))
		return 0;

	//m_pAnimMainFunction = (VSAnimMainFunction *)rStream.GetMapValue(GetNextLink());
	rStream.LinkObjectPtr(m_pAnimMainFunction);
	for(unsigned int i = 0 ; i < m_pAnimFunctionArray.GetNum() ; i++)
	{
		//m_pAnimFunctionArray[i] = (VSAnimBaseFunction *)rStream.GetMapValue(GetNextLink());
		rStream.LinkObjectPtr(m_pAnimFunctionArray[i]);
	}
	return 1;

}
bool VSAnimTree::Clone(const VSObject *pObject,unsigned int uiType)
{
	const VSAnimTree* Temp = DynamicCast<VSAnimTree>(pObject); 
	if(!Temp)
		return 0;
	if(VSController::Clone(pObject,uiType))
	{
		for(unsigned int i = 0 ; i < m_pAnimFunctionArray.GetNum() ; i++)
		{
			VSAnimBaseFunction * pAnimBaseFunction = m_pAnimFunctionArray[i];
			m_pAnimFunctionArray[i] = NULL;
			VSMAC_DELETE(pAnimBaseFunction);
		}
		m_pAnimFunctionArray.Clear();
		m_pAnimMainFunction = NULL;

		unsigned int uiAnimFuntionNum = Temp->m_pAnimFunctionArray.GetNum();
		m_pAnimFunctionArray.Clear();
		m_pAnimFunctionArray.SetBufferNum(uiAnimFuntionNum);

		VSAnimMainFunction * pAnimMainFunction = NULL;
		VSArray<VSPutNode *> OldLinkArray, NewLinkArray;

		for(unsigned int i = 0 ; i < uiAnimFuntionNum ;i++)
		{
			VSAnimBaseFunction * pTemp1  = Temp->m_pAnimFunctionArray[i];
			VSAnimBaseFunction * pTemp2 =(VSAnimBaseFunction *)VSObject::GetInstance((pTemp1)->GetType().GetName());
			pTemp2->SetObject(m_pObject);
			pTemp2->Clone(pTemp1,uiType);
			m_pAnimFunctionArray[i] = pTemp2;	
			m_pAnimFunctionArray[i]->SetOwner(this);
			pAnimMainFunction = DynamicCast<VSAnimMainFunction>(pTemp2);
			if(pAnimMainFunction)
			{
				m_pAnimMainFunction = pAnimMainFunction;
			}
			pTemp1->AddAllPutNodeTo(OldLinkArray);
			pTemp2->AddAllPutNodeTo(NewLinkArray);
		}
		for(unsigned int i = 0 ; i < uiAnimFuntionNum ;i++)
		{
			if(!m_pAnimFunctionArray[i]->Link(OldLinkArray,NewLinkArray))
				return 0;
		}
		VSMAC_ASSERT(m_pAnimMainFunction);
		return 1;

	}
	else
	{
		return 0;
	}

}
void VSAnimTree::DeleteAnimFunction(VSAnimBaseFunction * pAnimFunction)
{
	if(pAnimFunction)
	{
		for (unsigned int i = 0 ; i < m_pAnimFunctionArray.GetNum() ; i++)
		{
			if(m_pAnimFunctionArray[i] == pAnimFunction)
			{
				m_pAnimFunctionArray.Erase(i);
				return ;
			}
		}

	}
}
bool VSAnimTree::UpdateEx(double dAppTime)
{
	const VSSkelectonMeshNode * pMesh = GetSkelectonMeshNode();
	VSMAC_ASSERT(pMesh);
	if (!pMesh)
	{
		return false;
	}
	VSSkelecton * pSkelecton = pMesh->GetSkelecton();
	VSMAC_ASSERT(pSkelecton);
	if (!pSkelecton)
	{
		return false;
	}

	if (!pMesh->GetAnimSet())
	{
		return false;
	}
	if(!VSController::UpdateEx(dAppTime))
		return false;
	for(unsigned int i = 0 ; i < m_pAnimFunctionArray.GetNum() ; i++)
	{
		m_pAnimFunctionArray[i]->ClearFlag();
	}
	if(!m_pAnimMainFunction->Update(dAppTime))
		return false;
	return true;
}
bool VSAnimTree::SetObject(VSObject * pObject)
{
	VSSkelectonMeshNode* Temp = DynamicCast<VSSkelectonMeshNode>(pObject); 
	if(!Temp)
		return 0;
	m_pObject = pObject;
	return 1;
}
void VSAnimTree::ResetAnimFunction()
{
	for (unsigned int i = 0 ; i < m_pAnimFunctionArray.GetNum() ; i++)
	{
		VSAnimSequenceFunc * pAnimSequence = DynamicCast<VSAnimSequenceFunc>(m_pAnimFunctionArray[i]);
		if (pAnimSequence)
		{
			const VSAnim * pAnim = pAnimSequence->GetAnim();
			if (pAnim)
			{
				pAnimSequence->SetAnim(pAnim->m_cName);
			}
			
		}
	}
}
VSAnimBaseFunction *  VSAnimTree::GetAnimFunctionFromShowName(const VSUsedName & ShowName)
{
	for (unsigned int i = 0 ; i < m_pAnimFunctionArray.GetNum() ; i++)
	{
		if (m_pAnimFunctionArray[i]->GetShowName() == ShowName)
		{
			return m_pAnimFunctionArray[i];
		}
	}
	return NULL;
}
VSAnimTreeOneAnim::VSAnimTreeOneAnim(VSSkelectonMeshNode * pSkelectionMesh,const VSString& AnimName)
:VSAnimTree(pSkelectionMesh)
{
	VSAnimSequenceFunc* pAnimSequenceFunc = VS_NEW VSAnimSequenceFunc(_T("Squence"),this);
	m_pAnimMainFunction->GetInputNode(_T("Anim"))->Connection(pAnimSequenceFunc->GetOutputNode(0));
	pAnimSequenceFunc->SetAnim(AnimName);

}
VSAnimTreeOneAnim::~VSAnimTreeOneAnim()
{

}
VSAnimTreeOnlyIK::VSAnimTreeOnlyIK(VSSkelectonMeshNode * pSkelectionMesh,const VSString &IKRootBoneName)
:VSAnimTree(pSkelectionMesh)
{
	VSIKController * pIKController = VS_NEW VSIKController(_T("IKController"),this);
	m_pAnimMainFunction->GetInputNode(_T("IK"))->Connection(pIKController->GetOutputNode(0));
	pIKController->SetRootBoneName(IKRootBoneName);
}
VSAnimTreeOnlyIK::~VSAnimTreeOnlyIK()
{

}
VSAnimTreeTwoBlendAnim::VSAnimTreeTwoBlendAnim(VSSkelectonMeshNode * pSkelectionMesh,const VSString &AnimName1,const VSString &AnimName2)
:VSAnimTree(pSkelectionMesh)
{
	VSAnimSequenceFunc* pAnimSequenceFunc1 = VS_NEW VSAnimSequenceFunc(_T("Squence1"),this);
	
	pAnimSequenceFunc1->SetAnim(AnimName1);

	VSAnimSequenceFunc* pAnimSequenceFunc2 = VS_NEW VSAnimSequenceFunc(_T("Squence2"),this);

	pAnimSequenceFunc2->SetAnim(AnimName2);

	VSOneParamAnimBlend * pAnimBlend = VS_NEW VSOneParamAnimBlend(_T("OneParamBlend"),this);

	pAnimBlend->SetCrossFadingType(VSAnimBlendFunction::CFT_SMOOTH);
	pAnimBlend->SetNodeCrossFadingTime(0,1000.0f);
	pAnimBlend->SetNodeCrossFadingTime(1,1000.0f);

	pAnimBlend->GetInputNode(0)->Connection(pAnimSequenceFunc1->GetOutputNode(0));
	pAnimBlend->GetInputNode(1)->Connection(pAnimSequenceFunc2->GetOutputNode(0));

	m_pAnimMainFunction->GetInputNode(_T("Anim"))->Connection(pAnimBlend->GetOutputNode(0));

}
VSAnimTreeTwoBlendAnim::~VSAnimTreeTwoBlendAnim()
{

}
VSAnimTreeRectBlendAnim::VSAnimTreeRectBlendAnim(VSSkelectonMeshNode * pSkelectionMesh,
												 const VSString &AnimName1,
												 const VSString &AnimName2,
												 const VSString &AnimName3,
												 const VSString &AnimName4)
:VSAnimTree(pSkelectionMesh)
{
	VSAnimSequenceFunc* pAnimSequenceFunc1 = VS_NEW VSAnimSequenceFunc(_T("Squence1"),this);

	pAnimSequenceFunc1->SetAnim(AnimName1);

	VSAnimSequenceFunc* pAnimSequenceFunc2 = VS_NEW VSAnimSequenceFunc(_T("Squence2"),this);

	pAnimSequenceFunc2->SetAnim(AnimName2);

	VSAnimSequenceFunc* pAnimSequenceFunc3 = VS_NEW VSAnimSequenceFunc(_T("Squence3"),this);

	pAnimSequenceFunc1->SetAnim(AnimName3);

	VSAnimSequenceFunc* pAnimSequenceFunc4 = VS_NEW VSAnimSequenceFunc(_T("Squence4"),this);

	pAnimSequenceFunc2->SetAnim(AnimName4);


	VSRectAnimBlend * pAnimBlend = VS_NEW VSRectAnimBlend(_T("RectBlend"),this);

	pAnimBlend->SetCrossFadingType(VSAnimBlendFunction::CFT_IMMEDIATE);
	pAnimBlend->SetNodeCrossFadingTime(0,1000.0f);
	pAnimBlend->SetNodeCrossFadingTime(1,1000.0f);
	pAnimBlend->SetNodeCrossFadingTime(2,1000.0f);
	pAnimBlend->SetNodeCrossFadingTime(3,1000.0f);

	pAnimBlend->GetInputNode(0)->Connection(pAnimSequenceFunc1->GetOutputNode(0));
	pAnimBlend->GetInputNode(1)->Connection(pAnimSequenceFunc2->GetOutputNode(0));
	pAnimBlend->GetInputNode(2)->Connection(pAnimSequenceFunc3->GetOutputNode(0));
	pAnimBlend->GetInputNode(3)->Connection(pAnimSequenceFunc4->GetOutputNode(0));
	m_pAnimMainFunction->GetInputNode(_T("Anim"))->Connection(pAnimBlend->GetOutputNode(0));

}
VSAnimTreeRectBlendAnim::~VSAnimTreeRectBlendAnim()
{

}